/*
 * Copyright 2011 Angel Sanadinov
 *
 * This file is part of VBox WMI.
 *
 * VBox WMI is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VBox WMI is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VBox WMI.  If not, see <http://www.gnu.org/licenses/>.
 */

package ApplicationManagement;

import Utilities.Constants;
import Managers.SessionsManager;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * This class represents a session validation filter. <br><br>
 *
 * All requests for resources pass through this filter and user sessions are checked.
 * Should it be determined that a session is invalid, the client is redirected to
 * the login page (request for the login page and service are exempt).
 *
 * @author Angel Sanadinov
 */
public class SessionVerification implements Filter
{
    private ServletContext context;          //filter context
    private SessionsManager sessionsManager; //sessions manager

    /**
     * Initializes the filter.
     *
     * @param filterConfig filter configuration
     *
     * @throws ServletException if an exception occurs that interrupts the filter's
     *                          normal operation
     *
     * @see Filter#init()
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        context = filterConfig.getServletContext();
    }

    /**
     * Ends the filter's life-cycle and cleans up any object references.
     *
     * @see Filter#destroy()
     */
    @Override
    public void destroy()
    {
        context = null;
        sessionsManager = null;
    }

    /**
     * Processes the request. <br><br>
     *
     * Checks if the client has a valid session and if the requested resource can
     * be accessed. If the client does not have a valid session, it is redirected
     * to the login page.
     *
     * @param request a ServletRequest object that contains the request the
     *                client has made of the servlet
     * @param response a ServletResponse object that contains the response
     *                 the servlet sends to the client
     * @param chain the chain of filters to be executed for the request
     * 
     * @throws IOException if an input or output error is detected when the filter
     *                     handles the request
     * @throws ServletException if the request could not be handled
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
        //checks if the sessions manager is available and retrieves it, if not
        if(sessionsManager == null)
            sessionsManager = (SessionsManager)context.getAttribute(Constants.CONTEXT_SESSIONS_MANAGER);
        else
            ;

        //checks if an HTTP request was made and if the sessions manager was retrieved
        if(request instanceof HttpServletRequest && sessionsManager != null)
        {
            HttpServletRequest httpRequest = (HttpServletRequest)request;

            //retrieves the request URI
            String requestURI = httpRequest.getRequestURI();
            
            //checks if the requested resource is the login page/service or if the user session is available and is vailid
            if(requestURI.endsWith("/login.jsp") || requestURI.endsWith("/LoginService")
                    || sessionsManager.verifyUserSession(httpRequest.getSession(false)))
                chain.doFilter(request, response); //goes to the next filter or to the resource
            else //otherwise, the client needs to login and create a valid session
            {
                //redirects the client to the login page
                request.getRequestDispatcher("/login.jsp").forward(request, response);
                return;
            }
        }
        else //terminates the operation; w/o the proper data the client cannot be authenticated
            throw new ServletException("Failed to retrieve HTTP request object and/or sessions manager");
    }
}
